import { JwtService } from '@nestjs/jwt';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ResultCode } from '../../common/result/ResultCode';
import { IBaseService } from '../00_base/IBaseService';
import { SysUser } from '../02_user/entities/user.entity';
import { JwtPayload } from './jwt.payload';
import { generator } from '../../common/utils/generator';
import config from '../../app.config';
@Injectable()
export class JwtUtils {
  constructor(
    private jwt: JwtService, // 验签管理器（token）
    private baseService: IBaseService, // 基础service
  ) {}

  // 生成token的方法
  async generateToken(
    { id, username, nickname, deptId }: SysUser,
    roles,
    perms,
  ) {
    return this.jwt.sign(
      {
        userId: id,
        nickname: nickname,
        username: username,
        deptId: deptId,
        roles: roles,
        perms: perms,
        exp: Math.round(Date.now() / 1000) + 7200,
        key: config.Token.SECRET,
        jtl: generator.PrimaryKey(),
        ttl: 7200,
      },
      { secret: config.Token.SECRET },
    );
  }
  decodeToken(token: string): JwtPayload {
    if (token.startsWith('Bearer ')) {
      token = token.substr(7);
    }
    const decode = this.jwt.decode(token);
    return decode;
  }
  async verify(token: string): Promise<ResultCode<any>> {
    try {
      // token 不存在时退出
      if (token == null) {
        throw new UnauthorizedException(ResultCode.TOKEN_INVALID);
      }
      // token 验证是否携带 Bearer 开头
      if (!token.startsWith('Bearer ')) {
        throw new UnauthorizedException(ResultCode.TOKEN_INVALID);
      }
      token = token.substr(7);
      const verify: JwtPayload = this.jwt.verify(token, {
        secret: config.Token.SECRET,
      });
      // 验证token是否过期
      if (verify.exp - Date.now() / 1000 < 0) {
        return ResultCode.TOKEN_INVALID; // token过期或失效
      }
      // 验证是否是重新登陆用户
      const cacheToken = await this.baseService.redisGet(String(verify.userId));
      if (cacheToken == null || cacheToken != token) {
        return ResultCode.TOKEN_INVALID; // token过期或失效
      }
    } catch (e) {
      return ResultCode.TOKEN_INVALID; // token验证失败
    }
    return ResultCode.SUCCESS; // token验证成功
  }
}
